<?php
/**
 * 全局帮助函数集
 * User: Administrator
 * Date: 2017/11/9
 * Time: 20:46
 */


/**
 * 设置session,可以设置，获取等操作,还可以删除
 * 注册:session
 * 方法一: regSession('name.val') #name是键,val值
 * 方法一: regSession(['key' => $val, 'key1' => $val2]) #支持多个
 * 获取:session
 * 方法:session(key);
 * 清理所有session : session();
 * @param null $data
 * @param string $default
 * @return bool|string
 */
function session($data = null, $default = '')
{
    if ($data == null) {
        $_SESSION = [];
        return true;
    }
    if (is_array($data)) {//批量设置session
        foreach ($data as $key => $val) {
            $_SESSION[$key] = $val;
        }
    } else {
        if (strpos($data, '.') !== false) {//设置session
            list($name, $val) = explode('.', $data, 2);
            $_SESSION[$name] = $val;
        } elseif (strpos($data, '?') !== false) {//判断是否存在
            $name = str_replace('?', '', $data);
            return isset($_SESSION[$name]) ? true : false;
        } else {//获取session值
            return isset($_SESSION[$data]) ? $_SESSION[$data] : $default;
        }
    }
}

/**
 * 获取主域名
 * @return string
 */
function get_host()
{
    $http = $_SERVER['REQUEST_SCHEME'];
    $host = $_SERVER['HTTP_HOST'];
    return $http . '://' . $host;
}

/**
 * 判断是否是本地
 * @return bool
 */
function is_local()
{
    $list = ['::1', '127.0.0.1', 'localhost'];
    if (in_array($_SERVER['SERVER_ADDR'], $list)) {
        return true;
    }
    return false;
}

/**
 * 微信授权
 * @param $redirect_uri
 * @param bool $is_url
 * @return mixed|string
 */
function wx_auth_redirect($redirect_uri, $is_url = false)
{
    $state        = 'wx';
    $redirect_uri = urlencode($redirect_uri);
    $url          = config('wx.redirect_url');
    $app_id       = config('wx.app_id');
    $url          = sprintf($url, $app_id, $state, $redirect_uri);
    if ($is_url) {
        return $url;
    } else {
        header('Location:' . $url);
    }
}


/**
 * 微信授权拿 openid
 * @param $code
 * @return mixed
 */
function wx_auth_access_token($code)
{
    $app_id = config('wx.app_id');
    $secret = config('wx.app_secret');
    $url    = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code';
    $url    = sprintf($url, $app_id, $secret, $code);
    $result = getTo($url);
    return json_decode($result, true);
}

/**
 * 跳转
 * @param $url
 */
function redirect_url($url)
{
    header('Location:' . $url);
    exit();
}

/**
 * 数据库助手
 * @param null $table
 * @return MysqliConnect
 */
function db($table = null)
{
    static $db = null;
    if ($db === null) {
        if ($_SERVER['SERVER_ADDR'] == '127.0.0.1' || $_SERVER['SERVER_ADDR'] == '::1') {
            $cfg = config('local');
        } else {
            $cfg = config('online');
        }
        $db = new MysqliConnect($cfg['host'], $cfg['user'], $cfg['pass'], $cfg['db_name'], $cfg['prefix'], $cfg['port']);
    }
    if ($table != null) {
        return $db->from($table);
    }
    return $db;
}

/**
 * 初使系统必需
 */
function initSys()
{
    session_start();
    spl_autoload_register('autoLoadClass');
    set_error_handler('myErrorHandler');
    set_exception_handler('sysException');
}

function sysException($exception)
{
    myerror($exception->getMessage(), 'sysException');
}

function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    $error = array(
        'errorno' => $errno,
        'errstr'  => $errstr,
        'errfile' => $errfile,
        'errline' => $errline,
    );
    myerror($error, 'myErrorHandler');
}

/**
 * 写日志
 * @param $data
 * @param $flag
 * @param bool $is
 */
function mylog($data, $flag, $is = false)
{
    SgLogs::write($data, $flag, $is);
}

function myerror($data, $flag, $is = false)
{
    SgLogs::write($data, $flag, $is, 'error/' . date('Y-m-d'));
}

/**
 * 自动加载类
 * @param $className
 */
function autoLoadClass($className)
{
    $path = LIBRARY_ROOT . $className . '.class.php';
    if (is_file($path)) {
        require_once($path);
    } else {
        $path = LIBRARY_ROOT . $className . '.php';
        if (is_file($path)) {
            require_once($path);
        }
    }
}

/**
 * 友好时间显示，支持过云时和未来时
 * @param $timestamp int 时间戳
 * @return null|string
 */
function dateFormat($timestamp)
{
    if ($timestamp > time()) {
        $formats = array(
            'DAY'           => '还有%s天',
            'DAY_HOUR'      => '还有%s天%s小时',
            'HOUR'          => '还有%s小时',
            'HOUR_MINUTE'   => '还有%s小时%s分',
            'MINUTE'        => '还有%s分钟',
            'MINUTE_SECOND' => '还有%s分钟%s秒',
            'SECOND'        => '还有%s秒',
        );
        $seconds = $timestamp - time();
    } else {
        $formats = array(
            'DAY'           => '%s天前',
            'DAY_HOUR'      => '%s天%s小时前',
            'HOUR'          => '%s小时',
            'HOUR_MINUTE'   => '%s小时%s分前',
            'MINUTE'        => '%s分钟前',
            'MINUTE_SECOND' => '%s分钟%s秒前',
            'SECOND'        => '%s秒前',
        );
        $seconds = time() - $timestamp;
    }

    /* 计算出时间差 */

    $minutes = floor($seconds / 60);
    $hours   = floor($minutes / 60);
    $days    = floor($hours / 24);

    if ($days > 0) {
        $diffFormat = 'DAY';
    } else {
        $diffFormat = ($hours > 0) ? 'HOUR' : 'MINUTE';
        if ($diffFormat == 'HOUR') {
            $diffFormat .= ($minutes > 0 && ($minutes - $hours * 60) > 0) ? '_MINUTE' : '';
        } else {
            $diffFormat = (($seconds - $minutes * 60) > 0 && $minutes > 0)
                ? $diffFormat . '_SECOND' : 'SECOND';
        }
    }

    $dateDiff = null;
    switch ($diffFormat) {
        case 'DAY':
            $dateDiff = sprintf($formats[$diffFormat], $days);
            break;
        case 'DAY_HOUR':
            $dateDiff = sprintf($formats[$diffFormat], $days, $hours - $days * 60);
            break;
        case 'HOUR':
            $dateDiff = sprintf($formats[$diffFormat], $hours);
            break;
        case 'HOUR_MINUTE':
            $dateDiff = sprintf($formats[$diffFormat], $hours, $minutes - $hours * 60);
            break;
        case 'MINUTE':
            $dateDiff = sprintf($formats[$diffFormat], $minutes);
            break;
        case 'MINUTE_SECOND':
            $dateDiff = sprintf($formats[$diffFormat], $minutes, $seconds - $minutes * 60);
            break;
        case 'SECOND':
            $dateDiff = sprintf($formats[$diffFormat], $seconds);
            break;
    }
    return $dateDiff;
}


/**
 * 获取外部传参
 * @param $name
 * @param string $default
 * @return mixed|null|string
 */
function input($name, $default = '')
{
    if (strpos($name, '.')) { // 指定参数来源
        list($method, $name) = explode('.', $name, 2);
    } else { // 默认为自动判断
        $method = 'param';
    }
    switch (strtolower($method)) {
        case 'get'     :
            $input =& $_GET;
            break;
        case 'post'    :
            $input =& $_POST;
            break;
        case 'param'   :
            switch ($_SERVER['REQUEST_METHOD']) {
                case 'POST':
                    $input = $_POST;
                    break;
                default:
                    $input = $_GET;
            }
            break;
        case 'request' :
            $input =& $_REQUEST;
            break;
        case 'session' :
            $input =& $_SESSION;
            break;
        case 'cookie'  :
            $input =& $_COOKIE;
            break;
        case 'server'  :
            $input =& $_SERVER;
            break;
        case 'globals' :
            $input =& $GLOBALS;
            break;
        default:
            return null;
    }
    if (isset($input[$name])) {
        return $input[$name];
    }
    return $default;
}

/**
 * 密码加密方式
 * @param $pass
 * @param $salt
 * @return string
 */
function makePass($pass, $salt)
{
    return md5(md5($pass . $salt) . $salt);
}


/**
 * 过滤数据，防攻击
 */
function filterParams()
{
    if (!get_magic_quotes_gpc()) {
        if (!empty($_GET))
            $_GET = addslashes_deep($_GET);
        if (!empty($_POST))
            $_POST = addslashes_deep($_POST);
        $_COOKIE  = addslashes_deep($_COOKIE);
        $_REQUEST = addslashes_deep($_REQUEST);
    }
}

function addslashes_deep($value)
{
    if (empty($value)) {
        return $value;
    } else {
        if (is_array($value)) {
            $value = array_map('addslashes_deep', $value);
        } else {
            if (is_object($value)) {
                $value = json_encode($value);
            }
            $value = addslashes($value);
        }
        return $value;
    }
}

/**
 * 打印,支持多个
 * @param $data
 */
function dump($data)
{
    ob_start();
    $content = func_get_args();
    foreach ($content as $row) {
        if (is_array($row)) {
            var_dump($row);
        } else {
            print_r($row);
        }
        echo '<br/>';
    }
    $result = ob_get_contents();
    ob_end_clean();
    echo '<pre><xml>';
    echo $result;
    echo '</xml></pre>';
}

/**
 * 初使action使用
 * @param $class
 */
function initAction($class)
{
    $action = isset($_REQUEST['act']) ? trim($_REQUEST['act']) : '';
    if (!$action) {
        echo setJson(1000, 'act request not set');
        exit();
    }
    if (!class_exists($class)) {
        echo setJson(1001, 'class is not exists');
        exit();
    }
    $obj = new $class;
    if (!method_exists($obj, $action)) {
        echo setJson(1002, 'act request not exists');
        exit();
    }
    $result = call_user_func(array($obj, $action));
    if (!empty($result)) {
        if (is_array($result)) {
            echo json_encode($result);
        } else {
            echo $result;
        }
    }
}

/**
 * 设置返回信息
 * @param $code
 * @param string $msg
 * @param null $data
 * @return array
 */
function setResult($code, $msg = '', $data = null)
{
    $content = array(
        'status' => $code,
        'msg'    => $msg,
    );
    if ($msg == '' && config('error.' . $code)) {
        $content['msg'] = config('error.' . $code);
    }
    if ($data != null) {
        $content['data'] = $data;
    }
    return $content;
}

/**
 * 设置结果
 * @param $code
 * @param string $msg
 * @param null $data
 * @return string
 */
function setJson($code, $msg = '', $data = null)
{
    return json_encode(setResult($code, $msg, $data));
}

/**
 * 设置结果,自动退出,不再执行
 * @param $code
 * @param string $msg
 * @param null $data
 */
function exitJson($code, $msg = '', $data = null)
{
    exit(setJson($code, $msg, $data));
}

/**
 * 生成随机数
 * @param int $length 默认长度为32
 * @param int $mode 1小写，2大写，3数字　4混合
 * @return string
 */
function getNonce($length = 32, $mode = 3)
{

    switch ($mode) {
        case 1:
            $chars = '0123456789';
            break;
        case 2:
            $chars = 'abcdefghijklmnopqrstuvwxyz';
            break;
        default:
            $chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
            break;
    }
    $str = '';
    for ($i = 0; $i < $length; $i++) {
        $str .= $chars[mt_rand(0, strlen($chars) - 1)];
    }
    return $str;
}

/**
 * 存储健区分大小写
 * 获取和设置配置参数 支持批量定义,支持无限层
 *
 * 加载文件:config(include($file));支持多次加载
 * 加载文件:config(include($file), '键(文件名)');设置以文件名为键
 * 设置临时参数:config('a.b.c', 'abc');
 *
 * 获取所有的参数:config();
 * 获取单个值:config('a.b.c');
 *
 * @param string|array $name 配置变量
 * @param mixed $value 配置值
 * @param mixed $default 默认值
 * @see https://gitee.com/sgfoot/php-config
 * @author <root@sgfoot.com>
 * @return mixed
 */
function config($name = null, $value = null, $default = null)
{
    static $_config = array();
    if (!function_exists('array_get')) {
        /**
         * 获取key值,递归
         * @param $str string 以.隔开
         * @param $array array 多维数组
         * @return mixed|null
         */
        function array_get($str, $array)
        {
            $list   = explode('.', $str);
            $first  = array_shift($list);
            $result = isset($array[$first]) ? $array[$first] : null;
            if ($result && is_array($result) && count($list) > 0) {
                return array_get(join('.', $list), $result);
            }
            return $result;
        }
    }
    if (!function_exists('array_set')) {
        /**
         * 数组设置动态值
         * @param $str string 以.隔开的字符串
         * @param $val mixed 值
         * @param $array array 引用,目标数据
         * @return array
         */
        function array_set($str, $val, &$array)
        {
            $list  = explode('.', $str);
            $first = array_shift($list);
            if (count($list) > 0) {
                return array_set(join('.', $list), $val, $array[$first]);
            }
            $array[$first] = $val;
        }
    }
    // 无参数时获取所有
    if (is_null($name)) return $_config;
    // 优先执行设置获取或赋值
    if (is_string($name)) {
        $name = explode('.', $name);
        //获取值
        if (is_null($value)) {
            $rs = array_get(join('.', $name), $_config);
            return is_null($rs) ? $default : $rs;
        }
        //设置值
        array_set(join('.', $name), $value, $_config);
        return null;
    }
    //批量设置
    if (is_array($name)) {
        if (is_null($value)) {
            $_config = array_merge($_config, $name);
        } else {
            $_config = array_merge($_config, array($value => $name));
        }
        return null;
    }
    return null; // 避免非法参数
}

/**
 * 不同环境下获取真实的IP
 * @return array|false|string
 */
function get_ip()
{
    //判断服务器是否允许$_SERVER
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $realip = $_SERVER['REMOTE_ADDR'];
        }
    } else {
        //不允许就使用getenv获取
        if (getenv("HTTP_X_FORWARDED_FOR")) {
            $realip = getenv("HTTP_X_FORWARDED_FOR");
        } elseif (getenv("HTTP_CLIENT_IP")) {
            $realip = getenv("HTTP_CLIENT_IP");
        } else {
            $realip = getenv("REMOTE_ADDR");
        }
    }

    return $realip;
}

/**
 * post to
 * @param $url
 * @param $data
 * @param int $timeout
 * @param string $header
 * @return mixed
 */
function postTo($url, $data, $timeout = 5, $header = '')
{
    $curl = curl_init();
    //设置header
    if (!empty($header)) {
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    }
    curl_setopt($curl, CURLOPT_HEADER, FALSE);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_URL, $url); // url
    curl_setopt($curl, CURLOPT_POST, TRUE);
    curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // json数据
    $dataJson = curl_exec($curl); // 返回值
    if (curl_errno($curl) > 0) {
        curl_close($curl);
        return setJson(400, curl_error($curl));
    }
    curl_close($curl);
    return $dataJson;
}

/**
 * get 请求
 * @param $url
 * @param int $timeout
 * @return mixed|string
 */
function getTo($url, $timeout = 5)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);
    $dataJson = curl_exec($curl);
    if (curl_errno($curl) > 0) {
        curl_close($curl);
        return setJson(400, curl_error($curl));
    }
    curl_close($curl);
    return $dataJson;
}